package daemon;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Queue;

import server.EchoServer;
import server.mysqlConnection;

/**
 * This class is for our thread that responsible for checking in the background some things like, if subscriber Graduated or didn't return a book or to remind him
 * to return a book by email or if someone ordered a book and it's time to take the book, the book saved for two days and after that we need to delete him from
 * our table  saveorderlist.
 * @author Shay
 *
 */
public class Daemon implements Runnable
{
	
	private static final int DAY=86400000;

	@Override
	public void run() 
	{
			while(EchoServer.ServerAlive)
			{
				String[][] keyReturnDate=mysqlConnection.select("Select bid,copy,expectedReturnDate,returnDate,sid from borrow",5);
				String[][] keyGraduatedStudent=mysqlConnection.select("Select sid,GraduateDate from subscriber",2);
				for(int i=0;i<keyReturnDate.length;i++)
				{
					try 
					{
						if(keyReturnDate[i][3].compareTo("00/00/00")==0)
							isReturnDateLate(keyReturnDate[i][0],keyReturnDate[i][1],keyReturnDate[i][2]);//need also to inform librarian
					} 
					catch (ParseException e)
					{
						e.printStackTrace();
					}
				}
				for(int i=0;i<keyGraduatedStudent.length;i++)
				{
					try 
					{
						isGraduatedStudent(keyGraduatedStudent[i][0],keyGraduatedStudent[i][1]);
					} 
					catch (ParseException e)
					{
						e.printStackTrace();
					}
				}
				for(int i=0;i<keyReturnDate.length;i++)
				{
					try 
					{
						if(keyReturnDate[i][3].compareTo("00/00/00")==0)
							isOneDayBeforeReturn(keyReturnDate[i][4],keyReturnDate[i][2]);
					} 
					catch (ParseException e)
					{
						e.printStackTrace();
					}
				}
				
				
				/// check if two day passed and the subscriber didn't take the book, move the order to the next
				String[][] timePass=mysqlConnection.select("SELECT bid,copy,date FROM saveorderlist",3);
				for(int i=0; i<timePass.length ; i++)
				{
						DateFormat formatter=new SimpleDateFormat("yyyy/MM/dd");
						String info=(timePass[i][2]).toString();
						Calendar today=Calendar.getInstance();
						if(twoDaysPassed(info))   // means that two day passed
						{
								Queue<Integer> q=EchoServer.bookOrdersQueue.get(Integer.parseInt(timePass[i][0]));
								if(q.size()>0)
								{
									String currDate=formatter.format(today.getTime());	
									Integer sid=q.poll();
									// need to inform the subscriber that the book arrived - by email msg
									String[][] mailDetails=mysqlConnection.select("SELECT email FROM users WHERE id="+sid+";",1);
									EchoServer.sendEmailNotification(mailDetails[0][0],"Your book arrived, you can come and get it, we will save it for two days");
									mysqlConnection.update("UPDATE saveorderlist SET sid="+sid+", date="+"'"+currDate+"'"+" WHERE bid="+timePass[i][0]+" AND copy="+timePass[i][1]+";");
									mysqlConnection.update("DELETE FROM orders WHERE bid="+timePass[i][0]+" AND sid="+sid+";");
									mysqlConnection.update("UPDATE orders SET indexinqueue=indexinqueue-1 WHERE bid="+timePass[i][0]+";");	

								}
								else mysqlConnection.update("DELETE FROM saveorderlist WHERE bid="+timePass[i][0]+" AND copy="+timePass[i][1]+";");
						}

				}
				
		
				try 
				{
					Thread.sleep(DAY);
				} 
				catch (InterruptedException e) 
				{
					e.printStackTrace();
				}
			}
	}
	
	
	/**
	 * Check if subscriber return date is one day before return
	 * @param sid
	 * @param expectedReturnDate
	 * @return true/false
	 * @throws ParseException
	 */
	private boolean isOneDayBeforeReturn(String sid,String expectedReturnDate)  throws ParseException
	{
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE,1);
		DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
		String now = dateFormat.format(cal.getTime());
    	Date date1 = dateFormat.parse(now);
    	Date date2 = dateFormat.parse(expectedReturnDate);
    	if(date1.compareTo(date2)==0)//now + one day is equal to expectedReturnDate
    	{
    		String[][] WhoNeedToreturn=mysqlConnection.select("Select email from users where id="+sid,1);
    		EchoServer.sendEmailNotification(WhoNeedToreturn[0][0],"You need to return the book tomorrow");
    	}
		return false;
		
	}


	/**
	 * Check if return date late
	 * @param bid
	 * @param copy
	 * @param expectedReturnDate
	 * @return true/false
	 * @throws ParseException
	 */
	private boolean isReturnDateLate(String bid,String copy,String expectedReturnDate) throws ParseException 
	{
		Calendar cal = Calendar.getInstance();
		DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
		String now = dateFormat.format(cal.getTime());
		
		
    	Date date1 = dateFormat.parse(now);
    	Date date2 = dateFormat.parse(expectedReturnDate);

    	
    	if(date1.compareTo(date2)>0)//now is after expectedReturnDate
    	{
    		
    		mysqlConnection.update("update borrow set incident='Late' where bid="+bid+" and copy="+copy);
    		return true;
    	}
		return false;
	}
	
	
	/**
	 * Check if subscriber graduated
	 * @param sid
	 * @param GraduateDate
	 * @return true/false
	 * @throws ParseException
	 */
	private boolean isGraduatedStudent(String sid,String GraduateDate) throws ParseException 
	{
		Calendar cal = Calendar.getInstance();
		DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
		String now = dateFormat.format(cal.getTime());
		
		
    	Date date1 = dateFormat.parse(now);
    	Date date2 = dateFormat.parse(GraduateDate);

    	
    	if(date1.compareTo(date2)>0 || date1.compareTo(date2)==0)//now is today or after GraduateDate
    	{
    		String[][] ReturnDate=mysqlConnection.select("Select returnDate from borrow where sid="+sid+" and returnDate='00/00/00' ",1);
    		if(ReturnDate.length>0 && ReturnDate[0][0].compareTo("00/00/00")==0)//Still have books and need to return them
    		{
    			mysqlConnection.update("update subscriber set CardStatus='2' where sid="+sid);
    		}
    		else
    		{
    			mysqlConnection.update("update subscriber set CardStatus='0' where sid="+sid);
    		}
    		return true;
    	}
		return false;
	}
	
	
	
	/**
	 * This function check if two days passed from the date she gets. 
	 * @param dateInform 
	 * @return true - if two days passed else - false. 
	 */
	private Boolean twoDaysPassed (String dateInform)
	{
		try 
		{
			DateFormat formatter=new SimpleDateFormat("yyyy/MM/dd");
			Date date = (Date)formatter.parse(dateInform);
			Calendar informDate=Calendar.getInstance();
			informDate.setTime(date);
			informDate.add(Calendar.DATE, 2);
			Calendar today=Calendar.getInstance();
			if(today.compareTo(informDate)>0) return true; // means that two day passed
			else return false; 
		}
		catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace(); return false; 
		}
	}
	
	

}
